from utils import debug_info
import gc
from wol2 import wake_on_lan
from machine import Pin


class MQTTClient:
	def __init__(self, without_receive_msg: bool = False):
		from machine import Timer
		from config import Config
		from umqtt.simple import MQTTClient

		self._led = Pin(2, Pin.OUT, value=1)
		self._PERIODIC = Timer.PERIODIC
		self._without_receive_msg = without_receive_msg
		self._check_message_timer = Timer(3)

		self._client = MQTTClient(
			Config.MQTT.CLIENT_ID,
			Config.MQTT.HOST,
			Config.MQTT.PORT,
			Config.MQTT.USERNAME,
			Config.MQTT.PASSWORD,
			120
		)

	def deinit(self):
		self._check_message_timer.deinit()
		self._client.disconnect()

	def _client_topic_cb(self, topic, msg):
		print("\n- received topic: %s\n- message: %s" % (topic, msg))

		msg = bytes.decode(msg)

		# if msg == b'led_on':
		# 	pass
		# elif msg == b'led_off':
		# 	pass

		if msg.startswith("is_board_alive!!!"):
			self._led.off()  # value(not self._led.value())
		elif msg.startswith("turn_on_my_nas!!!"):
			mac_address = msg.split("!!!")[1]

			wake_on_lan(mac_address)
		else:
			pass

		gc.collect()

	def _check_message_cb(self, timer):
		try:
			self._client.check_msg()
		except OSError as e:
			if str(e) == "-1" or str(e) == "[Errno 104] ECONNRESET":
				debug_info("check message failed")

				self.restart()
			else:
				print(e)

		gc.collect()

	def publish(self, msg):
		from config import Config

		self._client.publish(Config.MQTT.TOPIC, msg)

		gc.collect()

	def publish_data_point(self, dp_id, **kwargs):
		import ujson
		from utime import sleep_ms

		if "temp" in kwargs:
			data = {
						"datastreams": [
							{
								"id": dp_id,
								"datapoints": [
									{
										"value": kwargs["temp"]
									}
								]
							},
						]
			}

			json = ujson.dumps(data)
			json_length = len(json)

			byte_data = bytearray(json_length + 3)
			byte_data[0] = 1  # 数据点类型值：1    //1： json格式1字符串
			byte_data[1] = int(json_length / 256)  # 固定两字节长度高位字节
			byte_data[2] = json_length % 256  # 固定两字节长度低位字节
			byte_data[3:] = json.encode("utf-8")  # json data

			debug_info("data point: %s" % byte_data)

			try:
				self._client.publish("$dp", byte_data)
			except OSError as e:
				if str(e) == "[Errno 104] ECONNRESET":
					debug_info("publish data point failed")
			finally:
				sleep_ms(500)

				self.restart()

			gc.collect()

	def start(self):
		from config import Config

		if not self._without_receive_msg:
			self._client.set_callback(self._client_topic_cb)

		self._client.connect(True)
		self._client.subscribe(Config.MQTT.TOPIC)

		debug_info("Connected to %s\nSubscribed topic %s\n" % (Config.MQTT.HOST, Config.MQTT.TOPIC))

		self._check_message_timer.init(
			mode=self._PERIODIC,
			period=100,
			callback=self._check_message_cb
		)

		gc.collect()

	def restart(self):
		debug_info("mqtt restart")

		self._check_message_timer.deinit()

		try:
			self._client.disconnect()
		finally:
			self.start()
